﻿
Imports System.IO

Namespace configNaming
    Namespace staticrequest
        Public Module staticrequest
            Public Const name As String = "static"
        End Module
    End Namespace
End Namespace

Public Class staticrequest
    Inherits cacheProcessor
    'a new static request handler, to handle direct by filename
    'such as /s/abc.def, so the browser & downloader can serve the filename correctly.
    'assume windows can handle ./abc.def same as .\abc.def

    Public Const staticfilepath As String = ".\static\"
    Public Const _pathidentity As String = "/s/"
    Protected Shared config As configParser
    Private section As String = Nothing

    Public Overrides Function pathidentity() As String
        Return _pathidentity
    End Function

    Public Shared Function filefullpath(ByVal filename As String) As String
        Return staticfilepath + filename
    End Function

#If RETIRED Then
    Protected Overridable Function filefullpath(ByVal filename As String) As String
        Return staticfilefullpath(filename)
    End Function
#End If

    'staticrequest only generate link according to input filename, and serve it according to new context & config
    'then can serve different file according to referer/ip and something else, make a more control here

    'always confirm in configuration, we can use both dir/filename and dir\filename
    'use only in processStaticFile
    Private Function staticfilename(ByRef filename As String _
                                    , ByVal context As httpContext _
                                    , ByVal config As configParser) As String
        Dim rtn As String = Nothing
        If config Is Nothing OrElse context Is Nothing Then
            rtn = filename
        Else
            strrplc(filename, filesystem.directorySeperator, network.pathSeperator)
            If Not config.trygetparameter(section, filename, rtn _
                                          , Nothing, context.generatefilters()) Then
                strrplc(filename, network.pathSeperator, filesystem.directorySeperator)
                If Not config.trygetparameter(section, filename, rtn _
                                              , Nothing, context.generatefilters()) Then
                    rtn = filename
                End If
            End If
        End If

        strrplc(rtn, network.pathSeperator, filesystem.directorySeperator)
        copy(filename, rtn)
        Return filename
    End Function

    Public Overrides Sub initial(Optional ByVal config As configParser = Nothing)
        MyBase.initial(config)
        staticrequest.config = config
    End Sub

    Protected Overridable Sub addresponseHeaders(ByVal context As httpContext, ByVal filename As String)
        Dim contentType As String = Nothing
        contentType = contentTypes.getdefaultContentType(filename)
        If isemptystring(contentType) Then
            raiseError("cannot get default content type for file " + filename _
                       + ", browsers may not be able to handle the response.", errorHandle.errorType.warning)
        End If
        context.setcontentType(contentType)
    End Sub

#If RETIRED Then
    Protected Overrides Sub addresponseHeaders(ByVal context As httpContext)
        MyBase.addresponseHeaders(context)
        addresponseHeaders(context, filename(context))
    End Sub
#End If

    Protected Function processStaticRequest(ByVal context As httpContext, ByVal filename As String) As Boolean
        If isemptystring(filename) Then
            raiseError("do not have filename, ignore request.", errorHandle.errorType.application)
            Return False
        Else
            filename = staticfilename(filename, context, config)
            On Error Resume Next
            Dim bytes() As Byte = Nothing
            bytes = File.ReadAllBytes(filefullpath(filename))
            If bytes Is Nothing Then
                raiseError("cannot find static file " + filefullpath(filename) + ", ignore request." _
                           , errorHandle.errorType.warning)
                Return False
            Else
                addresponseHeaders(context, filename)
                context.buff().Write(bytes, 0, bytes.Length())
                Return True
            End If
        End If
    End Function

    Protected NotOverridable Overrides Function processImpl(ByVal context As httpContext) As Boolean
        Return processStaticRequest(context, filename(context))
    End Function

    Public Shared Function generateStaticfileLinkUrl(ByVal filename As String) As String
        If Not isemptystring(filename) Then
            strrplc(filename, filesystem.directorySeperator, network.pathSeperator)
            Return strmid(_pathidentity, strlen(network.pathSeperator)) + filename
        Else
            Return Nothing
        End If
    End Function

    'get filename from context, this function called by both processImpl and addresponseHeaders
    Protected Overridable Function filename(ByVal context As httpContext) As String
        Return strmid(context.url().path, strlen(pathidentity()))
    End Function

    Public Sub New(Optional ByVal sectionNaming As String = configNaming.staticrequest.name)
        copy(section, sectionNaming)
    End Sub
End Class
